home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / widgets.zip / WIDGET.C < prev    next >
C/C++ Source or Header  |  1992-07-22  |  20KB  |  862 lines

  1. //  WIDGET.C
  2. //
  3. //  David Stafford
  4. //
  5. //  The widget-works.  Dirt-simple graphical object library for Windows.
  6. //
  7. //  11/25/91   first alpha
  8. //  12/12/91   added GetNextWidget, GetWidgetValuePtr
  9. //  01/07/92   new flicker-free (but more complicated) PaintWidget
  10. //  01/09/92   added IntersectWidgetRect, AbsHideWidget, AbsShowWidget
  11. //  01/17/92   replaced UserValue with 'Extra' bytes
  12. //  01/18/92   added GetWidgetMask, GetWidgetImage. Removed InternalGetWidget
  13. //  01/21/92   added WidgetsOverlap
  14. //  01/23/92   improved DrawBitmap and PaintWidget (added DrawHelper)
  15.  
  16. #include <windows.h>
  17. #include <stdlib.h>
  18. #include "widget.h"
  19.  
  20.  
  21. static HWIDGET FirstWidget = NULL;
  22.  
  23.  
  24. // Combines two bitmaps together to produce a third bitmap.
  25. // ROP-code goes in the BitBlt.
  26. // If Dest is NULL, it is created for you.
  27. // Returns destination bitmap.
  28. //
  29. // This function can be used to duplicate a bitmap by specifying Dest as
  30. // NULL and the original as both Src1 and Src2 and the Rop as SRCCOPY.
  31.  
  32. HBITMAP CDIST PASCAL CombineBitmaps( HBITMAP Dest, HBITMAP Src1, HBITMAP Src2, DWORD Rop )
  33.   {
  34.   HDC DC1, DC2;
  35.   BITMAP BitInfo;
  36.  
  37.   DC1 = CreateCompatibleDC( NULL );
  38.   DC2 = CreateCompatibleDC( NULL );
  39.  
  40.   GetObject( Src1, sizeof( BITMAP ), (LPSTR)&BitInfo );
  41.  
  42.   if( !Dest )  Dest = CreateBitmapIndirect( &BitInfo );
  43.  
  44.   SelectObject( DC1, Dest );
  45.   SelectObject( DC2, Src1 );
  46.  
  47.   BitBlt( DC1,
  48.           0,
  49.           0,
  50.           BitInfo.bmWidth,
  51.           BitInfo.bmHeight,
  52.           DC2,
  53.           0,
  54.           0,
  55.           SRCCOPY );
  56.  
  57.   SelectObject( DC2, Src2 );
  58.  
  59.   BitBlt( DC1,
  60.           0,
  61.           0,
  62.           BitInfo.bmWidth,
  63.           BitInfo.bmHeight,
  64.           DC2,
  65.           0,
  66.           0,
  67.           Rop );
  68.  
  69.   DeleteDC( DC1 );
  70.   DeleteDC( DC2 );
  71.  
  72.   return( Dest );
  73.   }
  74.  
  75.  
  76. // Used by DrawBitmap and PaintWidget to do the real work.
  77.  
  78. static void DrawHelper( HDC DC, int x, int y, int Width, int Height, HBITMAP Image, HBITMAP Mask )
  79.   {
  80.   HDC MemDC     = CreateCompatibleDC( NULL );
  81.   HDC AnotherDC = CreateCompatibleDC( NULL );
  82.   HBITMAP WorkBM;
  83.  
  84.   WorkBM = CreateCompatibleBitmap( DC, Width, Height );
  85.  
  86.   SelectObject( MemDC, WorkBM );
  87.  
  88.   BitBlt( MemDC,
  89.           0,
  90.           0,
  91.           Width,
  92.           Height,
  93.           DC,
  94.           x,
  95.           y,
  96.           SRCCOPY );
  97.  
  98.   if( Mask )
  99.     {
  100.     SelectObject( AnotherDC, Mask );
  101.  
  102.     BitBlt( MemDC,
  103.             0,
  104.             0,
  105.             Width,
  106.             Height,
  107.             AnotherDC,
  108.             0,
  109.             0,
  110.             SRCAND );
  111.     }
  112.  
  113.   SelectObject( AnotherDC, Image );
  114.  
  115.   BitBlt( MemDC,
  116.           0,
  117.           0,
  118.           Width,
  119.           Height,
  120.           AnotherDC,
  121.           0,
  122.           0,
  123.           Mask ? SRCINVERT : SRCCOPY );
  124.  
  125.   BitBlt( DC,
  126.           x,
  127.           y,
  128.           Width,
  129.           Height,
  130.           MemDC,
  131.           0,
  132.           0,
  133.           SRCCOPY );
  134.  
  135.   DeleteDC( MemDC );
  136.   DeleteDC( AnotherDC );
  137.   DeleteObject( WorkBM );
  138.   }
  139.  
  140.  
  141. // Just draws a simple bitmap on the display.
  142. // The mask is optional.
  143.  
  144. void CDIST PASCAL DrawBitmap( HDC DC, int x, int y, HBITMAP Image, HBITMAP Mask )
  145.   {
  146.   BITMAP BitInfo;
  147.  
  148.   GetObject( Image, sizeof( BITMAP ), (LPSTR)&BitInfo );
  149.  
  150.   DrawHelper( DC,
  151.               x,
  152.               y,
  153.               BitInfo.bmWidth,
  154.               BitInfo.bmHeight,
  155.               Image,
  156.               Mask );
  157.   }
  158.  
  159.  
  160. // Internal function to save the background image behind the widget in a bitmap.
  161.  
  162. static void SaveWidgetBackground( HDC DC, HWIDGET Widget )
  163.   {
  164.   HDC MemDC = CreateCompatibleDC( NULL );
  165.  
  166.   if( !Widget->Background )
  167.     {
  168.     Widget->Background = CreateCompatibleBitmap( DC, Widget->Size.x, Widget->Size.y );
  169.     }
  170.  
  171.   SelectObject( MemDC, Widget->Background );
  172.  
  173.   BitBlt( MemDC,
  174.           0,
  175.           0,
  176.           Widget->Size.x,
  177.           Widget->Size.y,
  178.           DC,
  179.           Widget->Rect.left,
  180.           Widget->Rect.top,
  181.           SRCCOPY );
  182.  
  183.   DeleteDC( MemDC );
  184.   }
  185.  
  186.  
  187. // Internal function to restore the background image behind the widget.
  188.  
  189. static void RestoreWidgetBackground( HDC DC, HWIDGET Widget )
  190.   {
  191.   HDC MemDC = CreateCompatibleDC( NULL );
  192.  
  193.   SelectObject( MemDC, Widget->Background );
  194.  
  195.   BitBlt( DC,
  196.           Widget->Rect.left,
  197.           Widget->Rect.top,
  198.           Widget->Size.x,
  199.           Widget->Size.y,
  200.           MemDC,
  201.           0,
  202.           0,
  203.           SRCCOPY );
  204.  
  205.   DeleteDC( MemDC );
  206.  
  207.   DeleteObject( Widget->Background );
  208.  
  209.   Widget->Background = NULL;
  210.   }
  211.  
  212.  
  213. // Internal function to paint a widget on the screen.
  214. // The DC can be NULL
  215.  
  216. static void PaintWidget( HDC DC, HWIDGET Widget )
  217.   {
  218.   HDC TempDC = DC;
  219.  
  220.   if( DC == NULL )  TempDC = GetDC( Widget->Wnd );
  221.  
  222.   DrawHelper( TempDC,
  223.               Widget->Rect.left,
  224.               Widget->Rect.top,
  225.               Widget->Size.x,
  226.               Widget->Size.y,
  227.               Widget->Image,
  228.               Widget->Mask );
  229.  
  230.   if( DC == NULL )  ReleaseDC( Widget->Wnd, TempDC );
  231.   }
  232.  
  233.  
  234. // Creates a new widget.  The mask is optional (use NULL if it doesn't exist).
  235. // The widget is initially hidden and put at location 0,0.
  236.  
  237. HWIDGET CDIST PASCAL CreateWidget( HWND Wnd, HBITMAP Image, HBITMAP Mask, int Extra )
  238.   {
  239.   WIDGET *Widget;
  240.   BITMAP BitInfo;
  241.  
  242.   if( (Widget = (WIDGET *)LocalAlloc( LMEM_FIXED, sizeof( WIDGET ) + Extra )) != NULL )
  243.     {
  244.     GetObject( Image, sizeof( BITMAP ), (LPSTR)&BitInfo );
  245.  
  246.     Widget->Wnd         = Wnd;
  247.     Widget->Size.x      = BitInfo.bmWidth;
  248.     Widget->Size.y      = BitInfo.bmHeight;
  249.     Widget->Rect.left   = 0;
  250.     Widget->Rect.top    = 0;
  251.     Widget->Rect.right  = BitInfo.bmWidth;
  252.     Widget->Rect.bottom = BitInfo.bmHeight;
  253.     Widget->Image       = Image;
  254.     Widget->Mask        = Mask;
  255.     Widget->Visible     = 0;
  256.     Widget->Background  = NULL;
  257.     Widget->Next        = FirstWidget;
  258.  
  259.     FirstWidget = Widget;
  260.     }
  261.  
  262.   return( Widget );
  263.   }
  264.  
  265.  
  266. // Moves a widget to a new location.
  267. // The DC can be NULL.
  268.  
  269. void CDIST PASCAL MoveWidget( HDC DC, HWIDGET Widget, int x, int y )
  270.   {
  271.   RECT NewRect, OldRect, Union;
  272.   POINT UnionSize;
  273.   HDC WorkDC, ScratchDC, TempDC = DC;
  274.   HBITMAP WorkBM;
  275.  
  276.   if( Widget->Rect.left == x && Widget->Rect.top == y )  return;
  277.  
  278.   NewRect.left   = x;
  279.   NewRect.top    = y;
  280.   NewRect.right  = x + Widget->Size.x;
  281.   NewRect.bottom = y + Widget->Size.y;
  282.  
  283.   if( !IsWidgetVisible( Widget ) )
  284.     {
  285.     Widget->Rect = NewRect;
  286.     return;
  287.     }
  288.  
  289.   if( DC == NULL )  TempDC = GetDC( Widget->Wnd );
  290.  
  291.   if( IntersectRect( &Union, &NewRect, &Widget->Rect ) )
  292.     {
  293.     UnionRect( &Union, &NewRect, &Widget->Rect );
  294.  
  295.     UnionSize.x = Union.right - Union.left;
  296.     UnionSize.y = Union.bottom - Union.top;
  297.  
  298.     WorkDC = CreateCompatibleDC( NULL );
  299.     WorkBM = CreateCompatibleBitmap( TempDC, UnionSize.x, UnionSize.y );
  300.     SelectObject( WorkDC, WorkBM );
  301.  
  302.     BitBlt( WorkDC,
  303.             0,
  304.             0,
  305.             UnionSize.x,
  306.             UnionSize.y,
  307.             TempDC,
  308.             Union.left,
  309.             Union.top,
  310.             SRCCOPY );
  311.  
  312.     ScratchDC = CreateCompatibleDC( NULL );
  313.     SelectObject( ScratchDC, Widget->Background );
  314.  
  315.     BitBlt( WorkDC,
  316.             Widget->Rect.left - Union.left,
  317.             Widget->Rect.top - Union.top,
  318.             Widget->Size.x,
  319.             Widget->Size.y,
  320.             ScratchDC,
  321.             0,
  322.             0,
  323.             SRCCOPY );
  324.  
  325.     BitBlt( ScratchDC,
  326.             0,
  327.             0,
  328.             Widget->Size.x,
  329.             Widget->Size.y,
  330.             WorkDC,
  331.             NewRect.left - Union.left,
  332.             NewRect.top - Union.top,
  333.             SRCCOPY );
  334.  
  335.     if( Widget->Mask )
  336.       {
  337.       SelectObject( ScratchDC, Widget->Mask );
  338.  
  339.       BitBlt( WorkDC,
  340.               NewRect.left - Union.left,
  341.               NewRect.top - Union.top,
  342.               Widget->Size.x,
  343.               Widget->Size.y,
  344.               ScratchDC,
  345.               0,
  346.               0,
  347.               SRCAND );
  348.       }
  349.  
  350.     SelectObject( ScratchDC, Widget->Image );
  351.  
  352.     BitBlt( WorkDC,
  353.             NewRect.left - Union.left,
  354.             NewRect.top - Union.top,
  355.             Widget->Size.x,
  356.             Widget->Size.y,
  357.             ScratchDC,
  358.             0,
  359.             0,
  360.             Widget->Mask ? SRCINVERT : SRCCOPY );
  361.  
  362.     DeleteDC( ScratchDC );
  363.  
  364. #if 0
  365.     // wait for vertical retrace
  366.     __emit__( 0xba, 0xda, 0x03,      //        mov  dx,03dah
  367.               0xec,                  // wait1: in   al,dx
  368.               0xa8, 0x08,            //        test al,8
  369.               0x75, 0xfb,            //        jnz  wait1
  370.               0xec,                  // wait2: in   al,dx
  371.               0xa8, 0x08,            //        test al,8
  372.               0x74, 0xfb );          //        jz   wait2
  373. #endif
  374.  
  375.     BitBlt( TempDC,
  376.             Union.left,
  377.             Union.top,
  378.             UnionSize.x,
  379.             UnionSize.y,
  380.             WorkDC,
  381.             0,
  382.             0,
  383.             SRCCOPY );
  384.  
  385.     DeleteDC( WorkDC );
  386.     DeleteObject( WorkBM );
  387.  
  388.     Widget->Rect = NewRect;
  389.     }
  390.   else
  391.     {
  392.     HideWidget( TempDC, Widget );
  393.  
  394.     Widget->Rect = NewRect;
  395.  
  396.     ShowWidget( TempDC, Widget );
  397.     }
  398.  
  399.   if( DC == NULL )  ReleaseDC( Widget->Wnd, TempDC );
  400.   }
  401.  
  402.  
  403. void FAR PASCAL LineDDAProc( int x, int y, ANIM_DATA FAR *Anim )
  404.   {
  405.   DWORD TimeUsed = GetTickCount() - Anim->StartTime;
  406.   WORD Budget = ((DWORD)Anim->Count * Anim->Speed) / Anim->Distance;
  407.  
  408.   if( TimeUsed <= Budget )
  409.     {
  410.     MoveWidget( Anim->DC, Anim->Widget, x, y );
  411.  
  412.     Yield();     // give background apps a chance
  413.     }
  414.  
  415.   ++Anim->Count;
  416.   }
  417.  
  418.  
  419. // Returns the number of pixels between two points.
  420. // (Not the exact distance.)
  421. // This is useful when you want to select the speed for the animation
  422. // so it remains somewhat constant across varying distances.
  423.  
  424. int CDIST PASCAL DistanceInPoints( int x1, int y1, int x2, int y2 )
  425.   {
  426.   return( max( abs( x1 - x2 ), abs( y1 - y2 ) ) + 1 );
  427.   }
  428.  
  429.  
  430. // Animates a widget to a new location.
  431. // The DC can be NULL.
  432. // The speed is the number of milliseconds between animations.
  433. // Instance should be NULL if linked with the DLL version.
  434.  
  435. void CDIST PASCAL AnimateWidget( HDC DC, HWIDGET Widget, int x, int y, int Speed, HANDLE Instance )
  436.   {
  437.   ANIM_DATA Anim;
  438.   FARPROC LineProc;
  439.  
  440.   Anim.Widget    = Widget;
  441.   Anim.DC        = DC;
  442.   Anim.Speed     = Speed;
  443.   Anim.StartTime = GetTickCount();
  444.   Anim.Distance  = DistanceInPoints( x, y, Widget->Rect.left, Widget->Rect.top );
  445.   Anim.Count     = 0;
  446.  
  447. #ifdef LINKABLE
  448.   LineProc = MakeProcInstance( (FARPROC)LineDDAProc, Instance );
  449.  
  450.   LineDDA( Widget->Rect.left,
  451.            Widget->Rect.top,
  452.            x,
  453.            y,
  454.            LineProc,
  455.            (LPSTR)&Anim );
  456.  
  457.   FreeProcInstance( (FARPROC)LineProc );
  458. #else
  459.   LineDDA( Widget->Rect.left,
  460.            Widget->Rect.top,
  461.            x,
  462.            y,
  463.            (FARPROC)LineDDAProc,
  464.            (LPSTR)&Anim );
  465. #endif
  466.  
  467.   MoveWidget( DC, Widget, x, y );
  468.   }
  469.  
  470.  
  471. // Destroys a widget.  Does not erase it from the display.
  472. // You must use HideWidget first.
  473.  
  474. void CDIST PASCAL DestroyWidget( HWIDGET Widget )
  475.   {
  476.   HWIDGET Prev;
  477.  
  478.   if( Widget->Background )  DeleteObject( Widget->Background );
  479.  
  480.   if( Widget == FirstWidget )
  481.     {
  482.     FirstWidget = Widget->Next;
  483.     }
  484.   else
  485.     {
  486.     for( Prev = FirstWidget; Prev->Next != Widget; Prev = Prev->Next )
  487.       ;
  488.  
  489.     Prev->Next = Widget->Next;
  490.     }
  491.  
  492.   LocalFree( (HANDLE)Widget );
  493.   }
  494.  
  495.  
  496. // Just like the name says.  Widget-cide.
  497.  
  498. void CDIST PASCAL DestroyAllWidgetsForTheWindow( HWND Wnd )
  499.   {
  500.   HWIDGET Widget;
  501.  
  502.   while( (Widget = GetNextWidget( Wnd, NULL )) != NULL )
  503.     {
  504.     DestroyWidget( Widget );
  505.     }
  506.   }
  507.  
  508.  
  509. // Decrements the widget's visibility count and hides it if the count is <= 0.
  510. // The DC can be NULL.
  511.  
  512. void CDIST PASCAL HideWidget( HDC DC, HWIDGET Widget )
  513.   {
  514.   HDC TempDC = DC;
  515.  
  516.   if( --Widget->Visible == 0 )
  517.     {
  518.     if( DC == NULL )  TempDC = GetDC( Widget->Wnd );
  519.  
  520.     RestoreWidgetBackground( TempDC, Widget );
  521.  
  522.     if( DC == NULL )  ReleaseDC( Widget->Wnd, TempDC );
  523.     }
  524.   }
  525.  
  526.  
  527. // Hides a widget.  Restores the background.
  528. // The DC can be NULL.
  529.  
  530. void CDIST PASCAL AbsHideWidget( HDC DC, HWIDGET Widget )
  531.   {
  532.   while( IsWidgetVisible( Widget ) )  HideWidget( DC, Widget );
  533.   }
  534.  
  535.  
  536. // Increments the widget's visibility count and shows it if the count is > 0.
  537. // The DC can be NULL.
  538.  
  539. void CDIST PASCAL ShowWidget( HDC DC, HWIDGET Widget )
  540.   {
  541.   HDC TempDC = DC;
  542.  
  543.   if( ++Widget->Visible == 1 )
  544.     {
  545.     if( DC == NULL )  TempDC = GetDC( Widget->Wnd );
  546.  
  547.     SaveWidgetBackground( TempDC, Widget );
  548.  
  549.     PaintWidget( TempDC, Widget );
  550.  
  551.     if( DC == NULL )  ReleaseDC( Widget->Wnd, TempDC );
  552.     }
  553.   }
  554.  
  555.  
  556. // Makes a widget visible.
  557. // The DC can be NULL.
  558.  
  559. void CDIST PASCAL AbsShowWidget( HDC DC, HWIDGET Widget )
  560.   {
  561.   while( !IsWidgetVisible( Widget ) )  ShowWidget( DC, Widget );
  562.   }
  563.  
  564.  
  565. // Used to dynamically change the look of a widget.
  566. // The DC can be NULL.
  567.  
  568. void CDIST PASCAL ChangeWidgetImage( HDC DC, HWIDGET Widget, HBITMAP Image, HBITMAP Mask )
  569.   {
  570.   BITMAP BitInfo;
  571.   int Visible;
  572.  
  573.   if( Widget->Image != Image )
  574.     {
  575.     if( Widget->Mask == Mask )   // if the mask didn't change it's much faster!
  576.       {
  577.       Widget->Image = Image;
  578.  
  579.       if( IsWidgetVisible( Widget ) )  PaintWidget( DC, Widget );
  580.       }
  581.     else
  582.       {
  583.       if( (Visible = Widget->Visible) > 0 )  AbsHideWidget( DC, Widget );
  584.  
  585.       GetObject( Image, sizeof( BITMAP ), (LPSTR)&BitInfo );
  586.  
  587.       Widget->Size.x      = BitInfo.bmWidth;
  588.       Widget->Size.y      = BitInfo.bmHeight;
  589.       Widget->Rect.right  = Widget->Rect.left + BitInfo.bmWidth;
  590.       Widget->Rect.bottom = Widget->Rect.top + BitInfo.bmHeight;
  591.       Widget->Image       = Image;
  592.       Widget->Mask        = Mask;
  593.  
  594.       if( Visible > 0 )  ShowWidget( DC, Widget );
  595.  
  596.       Widget->Visible     = Visible;
  597.       }
  598.     }
  599.   }
  600.  
  601.  
  602. // Invalidates any widgets which might be only partially obscured.
  603. // Sets the dirty flag for the redraw in RepaintWidgets.
  604. // Use this first in your WM_PAINT handler.
  605.  
  606. void CDIST PASCAL InvalidateWidgetsForPaint( HWND Wnd )
  607.   {
  608.   HWIDGET Widget;
  609.   HRGN Rgn = CreateRectRgn( 0, 0, 1, 1 );
  610.  
  611.   GetUpdateRgn( Wnd, Rgn, FALSE );
  612.  
  613.   for( Widget = FirstWidget; Widget; Widget = Widget->Next )
  614.     {
  615.     if( Widget->Wnd == Wnd )
  616.       {
  617.       Widget->Dirty = FALSE;
  618.  
  619.       if( IsWidgetVisible( Widget ) )
  620.         {
  621.         if( RectInRegion( Rgn, &Widget->Rect ) )
  622.           {
  623.           Widget->Dirty = TRUE;
  624.  
  625.           InvalidateRect( Wnd, &Widget->Rect, FALSE );
  626.           }
  627.         }
  628.       }
  629.     }
  630.  
  631.   DeleteObject( Rgn );
  632.   }
  633.  
  634.  
  635. // Repaints all the widgets belonging to a given window.
  636. // Use this after InvalidateWidgetsForPaint and the background
  637. // redraw in your WM_PAINT handler.
  638.  
  639. void CDIST PASCAL RepaintWidgets( HDC DC, HWND Wnd )
  640.   {
  641.   HWIDGET Widget;
  642.  
  643.   for( Widget = FirstWidget; Widget; Widget = Widget->Next )
  644.     {
  645.     if( Widget->Wnd == Wnd )
  646.       {
  647.       if( Widget->Dirty )
  648.         {
  649.         SaveWidgetBackground( DC, Widget );
  650.  
  651.         PaintWidget( DC, Widget );
  652.         }
  653.       }
  654.     }
  655.   }
  656.  
  657.  
  658. // Determines if a point is inside a widget.
  659. // The point is a pixel coordinate relative to the window.
  660.  
  661. BOOL CDIST PASCAL IsPointInWidget( HWIDGET Widget, int x, int y )
  662.   {
  663.   POINT Pt;
  664.   HDC MemDC;
  665.   BOOL Res = FALSE;
  666.  
  667.   Pt.x = x;
  668.   Pt.y = y;
  669.  
  670.   if( PtInRect( &Widget->Rect, Pt ) )
  671.     {
  672.     if( Widget->Mask == NULL )
  673.       {
  674.       Res = TRUE;
  675.       }
  676.     else
  677.       {
  678.       MemDC = CreateCompatibleDC( NULL );
  679.  
  680.       SelectObject( MemDC, Widget->Mask );
  681.  
  682.       Res = GetPixel( MemDC, x - Widget->Rect.left, y - Widget->Rect.top ) == RGB( 0, 0, 0 );
  683.  
  684.       DeleteDC( MemDC );
  685.       }
  686.     }
  687.  
  688.   return( Res );
  689.   }
  690.  
  691.  
  692. // Determines which widget lies at a given point in a window.
  693. // The point is a pixel coordinate relative to the window.
  694.  
  695. HWIDGET CDIST PASCAL WidgetHitTest( HWND Wnd, int x, int y )
  696.   {
  697.   HWIDGET Widget;
  698.   POINT Pt;
  699.   HDC MemDC = CreateCompatibleDC( NULL );
  700.  
  701.   Pt.x = x;
  702.   Pt.y = y;
  703.  
  704.   for( Widget = FirstWidget; Widget; Widget = Widget->Next )
  705.     {
  706.     if( Widget->Wnd == Wnd && IsWidgetVisible( Widget ) )
  707.       {
  708.       if( PtInRect( &Widget->Rect, Pt ) )
  709.         {
  710.         if( Widget->Mask == NULL )  break;
  711.  
  712.         SelectObject( MemDC, Widget->Mask );
  713.  
  714.         if( GetPixel( MemDC, x - Widget->Rect.left, y - Widget->Rect.top ) == RGB( 0, 0, 0 ) )  break;
  715.         }
  716.       }
  717.     }
  718.  
  719.   DeleteDC( MemDC );
  720.  
  721.   return( Widget );
  722.   }
  723.  
  724.  
  725. // Determines if a widget intersects a given rectangle.
  726. // If Inter is not NULL it will set it to the intersection.
  727.  
  728. BOOL CDIST PASCAL IntersectWidgetRect( HWIDGET Widget, RECT DDIST *Rect, RECT DDIST *Inter )
  729.   {
  730.   BOOL Ret;
  731.   RECT Dest;
  732.  
  733.   Ret = IntersectRect( &Dest, &Widget->Rect, Rect );
  734.  
  735.   if( Inter )  *Inter = Dest;
  736.  
  737.   return( Ret );
  738.   }
  739.  
  740.  
  741. // Useful for enumerating all the widgets for a window.
  742. // Use NULL as the widget to get the first widget.
  743. // Returns the next widget or NULL if at the end of the list.
  744.  
  745. HWIDGET CDIST PASCAL GetNextWidget( HWND Wnd, HWIDGET Widget )
  746.   {
  747.   if( Widget == NULL )  Widget = FirstWidget;
  748.   else                  Widget = Widget->Next;
  749.  
  750.   while( Widget && Widget->Wnd != Wnd )
  751.     {
  752.     Widget = Widget->Next;
  753.     }
  754.  
  755.   return( Widget );
  756.   }
  757.  
  758.  
  759. // Determines if one widget overlaps another.
  760. //
  761. // Note that this test uses only the widget rectangles and
  762. // isn't as precise as a test which would take into account
  763. // the masks.  But, this is good enough for now.
  764. //
  765. // If Widget2 is NULL all widgets in the same window are tested.
  766.  
  767. BOOL CDIST PASCAL WidgetsOverlap( HWIDGET Widget1, HWIDGET Widget2 )
  768.   {
  769.   RECT Dummy;
  770.  
  771.   if( Widget2 )
  772.     {
  773.     if( !IsWidgetVisible( Widget2 ) )  return( FALSE );
  774.  
  775.     return( IntersectRect( &Dummy, &Widget1->Rect, &Widget2->Rect ) );
  776.     }
  777.   else
  778.     {
  779.     while( (Widget2 = GetNextWidget( Widget1->Wnd, Widget2 )) != NULL )
  780.       {
  781.       if( Widget2 != Widget1 && IsWidgetVisible( Widget2 ) )
  782.         {
  783.         if( IntersectRect( &Dummy, &Widget1->Rect, &Widget2->Rect ) )
  784.           {
  785.           return( TRUE );
  786.           }
  787.         }
  788.       }
  789.  
  790.     return( FALSE );
  791.     }
  792.   }
  793.  
  794.  
  795. ////////////////////////////////////////////////////////////////////////////
  796.  
  797. #ifndef LINKABLE
  798.  
  799.  
  800. BOOL CDIST PASCAL IsWidgetVisible( HWIDGET Widget )
  801.   {
  802.   return( Widget->Visible > 0 );
  803.   }
  804.  
  805.  
  806. POINT CDIST PASCAL GetWidgetPoint( HWIDGET Widget )
  807.   {
  808.   return( *(POINT *)&(Widget->Rect.left) );
  809.   }
  810.  
  811.  
  812. HBITMAP CDIST PASCAL GetWidgetImage( HWIDGET Widget )
  813.   {
  814.   return( Widget->Image );
  815.   }
  816.  
  817.  
  818. HBITMAP CDIST PASCAL GetWidgetMask( HWIDGET Widget )
  819.   {
  820.   return( Widget->Mask );
  821.   }
  822.  
  823.  
  824. POINT CDIST PASCAL GetWidgetSize( HWIDGET Widget )
  825.   {
  826.   return( Widget->Size );
  827.   }
  828.  
  829.  
  830. void CDIST PASCAL GetWidgetRect( HWIDGET Widget, RECT DDIST *Rect )
  831.   {
  832.   *Rect = Widget->Rect;
  833.   }
  834.  
  835.  
  836. void DDIST * CDIST PASCAL GetWidgetExtra( HWIDGET Widget )
  837.   {
  838.   return( ((char *)(Widget) + sizeof( WIDGET )) );
  839.   }
  840.  
  841.  
  842. // Returns the version number of the Widget DLL.
  843.  
  844. int CDIST PASCAL GetVersionNumber( void )
  845.   {
  846.   return( 4 );
  847.   }
  848.  
  849.  
  850. int CDIST PASCAL LibMain( HANDLE Module, WORD DataSeg, WORD HeapSize, LPSTR CmdLine )
  851.   {
  852.   return( 1 );
  853.   }
  854.  
  855.  
  856. int CDIST PASCAL WEP( int SystemExit )
  857.   {
  858.   return( 1 );
  859.   }
  860.  
  861. #endif
  862.